/****************************************
* James Gomez                           *
* Project 3: Target Practice P3         *
* Comp 465                              *
* Professor Barnes                      *
* 12/7/2012                             *
*****************************************/

#ifndef _TORPEDO_
#define _TORPEDO_

#include "GomezJamesP3_OpenGL.h"

#include "GomezJamesP3_CollidableObject.cpp"
#include "GomezJamesP3_Movable.cpp"
#include "GomezJamesP3_Explodable.cpp"

using namespace std;


class Torpedo: public CollidableObject, Movable, public Explodable{

private:
	Color color[3];
	bool gravity;
	GLfloat GM[16];

protected:
	int lifespan, frameCount; 
	bool armed;

public:
	Torpedo(static const Color color[3], const int lifespan, const GLfloat startM[16]);
	~Torpedo(){};

	void draw();
	void move();

	bool isGravityOn(){ return gravity; }
	void setGravity(bool flag){ gravity  = flag; }
	bool isArmed() const{ return armed; }

	/* Child classes of Torpedo should override this method to 
	define homing capabilities specific to that torpedo type. */
	virtual void seekTarget(){};

	void resetGM();
};


Torpedo::Torpedo(static const Color color[3], const int lifespan, const GLfloat startM[16]): 
	CollidableObject("Torpedo", 40), Explodable(){
	
	setTM(startM);
	this->lifespan = lifespan;
	frameCount = 0;
	armed = false;

	for (int i=0; i<3; i++)
		this->color[i] = color[i];	

}

void Torpedo::draw(){

	if (isActive){

		if (isExploding){
			drawExplosion(TM);
		}
		else{
			glMatrixMode(GL_MODELVIEW);
			glPushMatrix();	
			glMultMatrixf(this->TM);
			glColor3fv(color);
			glutSolidSphere(25, SPHERE_SLICES, SPHERE_STACKS);
			glPopMatrix();
		}

	}
		
}

void Torpedo::move(){	
	//unless seekTarget() is overriden in a child class,
	//torpedo will default to straight path movement
	if (isActive){
		if (isExploding){
			explode();
			armed = false;
		}
		else{
			glMatrixMode(GL_MODELVIEW);
			//glPushMatrix();

			if (armed)
				seekTarget(); //does nothing unless overriden

			if(gravity){
				glPushMatrix();
				GLfloat distanceFromSun = getLocationV().magnitude();
				GLfloat gravityForce = GRAVITY_CONST/(distanceFromSun*distanceFromSun);
				abs(gravityForce);				
				GLfloat frameChange = distanceFromSun/gravityForce;
				GLfloat x,y,z;
				x = getX()/frameChange;
				y = getY()/frameChange;
				z = getZ()/frameChange;
				glLoadIdentity();
				glTranslatef(-x, -y, -z);
				glGetFloatv(GL_MODELVIEW_MATRIX, GM);
				glPopMatrix();
			}

			glPushMatrix();
			glLoadMatrixf(TM);
			glMultMatrixf(OM); //apply rotation
			glMultMatrixf(GM); //apply gravity
			glTranslatef(0, 0, MISSILE_SPEED); //apply forward translation
			glGetFloatv(GL_MODELVIEW_MATRIX, TM);
			resetOM();
			glPopMatrix();

			frameCount++;
			
			if(frameCount >= 50){
				armed = true;
			}
			
			if(armed && frameCount >= lifespan)
				isExploding = true;				
		}
	}	
	
}

void Torpedo::resetGM(){
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();
	glLoadIdentity();
	glGetFloatv(GL_MODELVIEW_MATRIX, GM);
	glPopMatrix();
}


#endif